import win32serviceutil
import win32service
import win32event
import servicemanager
import sys
import os
import subprocess
from dotenv import load_dotenv  # 新增

# 设置项目根目录和环境变量（从 .env 读取）
PROJECT_ROOT = "d:\\AI\\Flask"
os.chdir(PROJECT_ROOT)
load_dotenv(os.path.join(PROJECT_ROOT, ".env"))  # 新增：加载 .env 文件

# 从环境变量读取（原硬编码替换为）
os.environ["AWS_ACCESS_KEY_ID"] = os.getenv("AWS_ACCESS_KEY_ID")
os.environ["AWS_SECRET_ACCESS_KEY"] = os.getenv("AWS_SECRET_ACCESS_KEY")
os.environ["AWS_DEFAULT_REGION"] = os.getenv("AWS_DEFAULT_REGION", "us-east-1")
os.environ["AWS_DEFAULT_OUTPUT"] = os.getenv("AWS_DEFAULT_OUTPUT", "json")
print(os.environ["AWS_ACCESS_KEY_ID"])
class GradioService(win32serviceutil.ServiceFramework):
    _svc_name_ = "GradioChatService"  # 服务名称（唯一）
    _svc_display_name_ = "Gradio Chat Service"  # 服务显示名称
    _svc_description_ = "Windows 服务封装的 Gradio 聊天应用"  # 服务描述

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.is_running = False
        self.process = None

    def SvcDoRun(self):
        """服务启动时执行的逻辑"""
        servicemanager.LogMsg(
            servicemanager.EVENTLOG_INFORMATION_TYPE,
            servicemanager.PYS_SERVICE_STARTED,
            (self._svc_name_, '')
        )
        self.is_running = True

        # 启动 gui.py（使用虚拟环境的 Python 路径）
        python_path = os.path.join(PROJECT_ROOT, "venv", "Scripts", "python.exe")
        script_path = os.path.join(PROJECT_ROOT, "app", "static", "UI", "gui.py")
        try:
            self.process = subprocess.Popen(
                [python_path, script_path],
                cwd=PROJECT_ROOT,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,  # 合并标准错误到标准输出
                text=True,  # 以文本模式读取输出
                bufsize=1,  # 行缓冲
                universal_newlines=True
            )
            # 读取子进程输出（避免阻塞）
            while self.is_running:
                output = self.process.stdout.readline()
                if output:
                    servicemanager.LogInfoMsg(f"gui.py 输出: {output.strip()}")  # 记录到事件日志
                # 检查子进程是否退出
                if self.process.poll() is not None:
                    servicemanager.LogErrorMsg("gui.py 进程意外退出，退出码: {self.process.returncode}")
                    self.is_running = False
                    break
                win32event.WaitForSingleObject(self.hWaitStop, 1000)  # 缩短等待时间
        except Exception as e:
            servicemanager.LogErrorMsg(f"启动 gui.py 失败: {str(e)}")
            self.is_running = False

        # 等待服务停止信号（原循环调整）
        while self.is_running:
            win32event.WaitForSingleObject(self.hWaitStop, 5000)

    def SvcStop(self):
        """服务停止时执行的逻辑"""
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        self.is_running = False
        if self.process:
            self.process.terminate()  # 终止 gui.py 进程
        win32event.SetEvent(self.hWaitStop)
        servicemanager.LogMsg(
            servicemanager.EVENTLOG_INFORMATION_TYPE,
            servicemanager.PYS_SERVICE_STOPPED,
            (self._svc_name_, '')
        )

if __name__ == '__main__':
    try:
        if len(sys.argv) == 1:
            servicemanager.Initialize()
            servicemanager.PrepareToHostSingle(GradioService)
            servicemanager.StartServiceCtrlDispatcher()
        else:
            win32serviceutil.HandleCommandLine(GradioService)
    except Exception as e:
        # 记录异常到事件日志（可通过 eventvwr.msc 查看）
        servicemanager.LogErrorMsg(f"服务初始化失败: {str(e)}")
        raise  # 保留原始异常栈